package codeGeneration;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import util.HeaderOfJavaFile;

import lexer.TokenConstant;

public class BeanGenerator extends Generator {
	private List<Control> controls;
	private Map<String, Boolean> checks;
	private String defaultClassName;
	private String fileLocation;
	private String packageName;
	private StringBuffer sbuffWriter;
	private HeaderOfJavaFile headerOfJavaFile;

	public BeanGenerator(String srcPath, String packageName,
			ActionForm actionForm) {
		super();
		checks = new HashMap<String, Boolean>();
		this.controls = actionForm.getControls();
		this.packageName = packageName;

		this.defaultClassName = actionForm.getBeanName();
		this.fileLocation = srcPath + '/' + packageName.replace('.', '/') + '/'
				+ defaultClassName + ".java";

		File beanDir = new File(srcPath + '/' + packageName.replace('.', '/'));
		if (!beanDir.exists())
			beanDir.mkdir();

		sbuffWriter = new StringBuffer();
		headerOfJavaFile = new HeaderOfJavaFile();
		indentOneTime(HeaderOfJavaFile.packageNamePlaceHolder, null, ";\n",
				sbuffWriter, true);
		indentOneTime(HeaderOfJavaFile.importsListPlaceHolder, null, "",
				sbuffWriter, true);

	}

	// public Table tableDatabaseAdapter() {
	// Table table = new Table();
	// Map<String, Boolean> map = new HashMap<String, Boolean>();
	//
	// // Name of table
	// table.setName(actionForm.getName());
	//
	// // Add Id to Database table
	//
	// TableField tableField = new TableField();
	// tableField.setType(TokenConstant.INT);
	// tableField.setName(""
	// + ((char) (actionForm.getName().charAt(0) + 32))
	// + actionForm.getName().substring(1,
	// actionForm.getName().length()) + "id");
	// tableField.addExtraValue(TokenConstant.PK);
	// tableField.addExtraValue(TokenConstant.AUTOINCREASE);
	// table.addField(tableField);
	//
	// // -----------------------------------------------------
	//
	// for (int i = 0; i < controls.size(); ++i) {
	// Control c = controls.get(i);
	// if (isAttribute(c.getType())) {
	// String name = c.getControlName();
	// if (!map.containsKey(name)) {
	// map.put(name, true);
	// tableField = new TableField();
	// tableField.setType(getTokenInTableAdapter(c.getType()));
	// tableField.setName(name);
	// if (getTokenInTableAdapter(c.getType()) == TokenConstant.VARCHAR)
	// tableField.setLength(30);
	//
	// table.addField(tableField);
	// }
	// }
	// }
	//
	// return table;
	// }
	//
	// private int getTokenInTableAdapter(int type) {
	// switch (type) {
	// case TokenConstant.TEXTAREA:
	// case TokenConstant.TEXTFIELD:
	// case TokenConstant.PASSWORD:
	// return TokenConstant.VARCHAR;
	//
	// case TokenConstant.RADIOBUTTON:
	// return TokenConstant.VARCHAR;
	// case TokenConstant.CHECKBOX:
	// return TokenConstant.VARCHAR;
	// }
	//
	// return -1;
	// }

	public void generateBean() {
		if (controls == null)
			return;

		File beanFile = new File(fileLocation);
		if (beanFile.exists())
			return;

		headerOfJavaFile.setPackageName(packageName);
		generateClassBean();

		replacePlaceHolder(sbuffWriter, headerOfJavaFile);

		FileWriter fileWriter = null;
		try {
			fileWriter = getFileWriter(fileLocation);
			fileWriter.append(sbuffWriter.toString());
		} catch (IOException e1) {
			e1.printStackTrace();
		}

		closeFileWriter(fileWriter);
	}

	private void generateClassBean() {
		indentOneTime("public class " + defaultClassName, null, " {",
				sbuffWriter, false);
		generateAttributes();

		for (int i = 0; i < controls.size(); ++i) {
			Control c = controls.get(i);
			if (checks.containsKey(c.getControlName())) {
				if (c.getType() == TokenConstant.CHECKBOX
						&& ((i < controls.size() - 1) && controls.get(i + 1)
								.getType() == TokenConstant.CHECKBOX))
					generateMethod(c, true);
				else
					generateMethod(c, false);
				checks.remove(c.getControlName());
			}
		}

		decreaseIndentOneTime("}", sbuffWriter);
	}

	private void generateAttributes() {
		for (int i = 0; i < controls.size(); ++i) {
			Control c = controls.get(i);
			if (isAttribute(c.getType())) {
				String name = c.getControlName();
				if (!checks.containsKey(name)) {
					if (c.getType() == TokenConstant.CHECKBOX
							&& ((i < controls.size() - 1) && controls
									.get(i + 1).getType() == TokenConstant.CHECKBOX)) {
						indentOneTime("private "
								+ getTypeOfControl(c.getType()) + "[] " + name,
								null, ";", sbuffWriter, true);

					} else
						indentOneTime("private "
								+ getTypeOfControl(c.getType()) + ' ' + name,
								null, ";", sbuffWriter, true);
					checks.put(name, true);
				}
			}
		}

		sbuffWriter.append('\n');
	}

	private void generateMethod(Control c, boolean isArray) {
		String lowerCaseName = c.getControlName();

		String upperCaseName;
		upperCaseName = "" + ((char) (lowerCaseName.charAt(0) - 32))
				+ lowerCaseName.substring(1, lowerCaseName.length());

		indentOneTime("public void set" + upperCaseName, null, "("
				+ getTypeOfControl(c.getType()) + (isArray ? "[] " : ' ')
				+ lowerCaseName + ") {", sbuffWriter, false);
		appendToFile(sbuffWriter, "this." + lowerCaseName + " = "
				+ lowerCaseName + ";\n");
		decreaseIndentOneTime("}\n", sbuffWriter);

		indentOneTime("public " + getTypeOfControl(c.getType())
				+ (isArray ? "[]" : "") + " get" + upperCaseName, null,
				" () {", sbuffWriter, false);
		appendToFile(sbuffWriter, "return " + lowerCaseName + ";\n");
		decreaseIndentOneTime("}\n", sbuffWriter);
	}

	private String getTypeOfControl(int type) {
		switch (type) {
		case TokenConstant.TEXTAREA:
		case TokenConstant.TEXTFIELD:
		case TokenConstant.PASSWORD:
			return "String";

		case TokenConstant.RADIOBUTTON:
			return "String";
		case TokenConstant.CHECKBOX:
			return "String";
		case TokenConstant.RADIOBUTTONS:
			return "boolean[]";
		case TokenConstant.CHECKBOXES:
		case TokenConstant.SELECT:
			return "String[]";
		}

		return null;
	}

	private boolean isAttribute(int type) {
		if (type == TokenConstant.SUBMIT || type == TokenConstant.BUTTON)
			return false;
		return true;
	}
}